/**
 * 基于 <Tooltip> 的菜单组件
 */
import { MoreOutlined } from '@ant-design/icons'
import { truthy } from '@gnlab/utils'
import { Tooltip } from 'antd'
import type { TooltipPropsWithTitle } from 'antd/lib/tooltip'
import c from 'classnames'
import './index.less'

export interface MenuItem {
  icon?: React.ReactNode
  title: string
  onClick: (e: React.MouseEvent<HTMLAnchorElement>) => void
  disabled?: boolean
  disabledTips?: React.ReactNode // 解释菜单项禁用原因
}

export default function BeautyMenu(
  props: Omit<TooltipPropsWithTitle, 'title'> & {
    items: MenuItem[] | null
    children?: JSX.Element
  },
) {
  const {
    items,
    children = <MoreOutlined className="qun-beauty-menu-more" />,
    overlayClassName,
    ...tooltipProps
  } = props

  // 菜单被点击时应该关闭菜单。tooltip 自己貌似没有实现此效果，因此手动实现
  const [isForceHide, setIsForceHide] = useState(false)
  const forceHide = useCallback(() => {
    setIsForceHide(true)
    const timeoutId = setTimeout(() => setIsForceHide(false))
    return () => clearTimeout(timeoutId)
  }, [])

  // force hide 的时候直接返回 children，不返回 <Tooltip /> 的部分，就能做到平滑地隐藏菜单（单纯设置 visible 会有闪烁）
  if (isForceHide) return children

  const tooltipTitle = items
    ? items.map((item, i) => <MenuItemCom
        key={`${i}-${item.title}`}
        item={item}
        hideMenu={forceHide}
      />)
    : null

  return <Tooltip
    placement="rightTop"
    {...tooltipProps}
    title={tooltipTitle}
    overlayClassName={c('qun-beauty-menu', overlayClassName)}
  >
    <span
      onClick={e => {
        e.stopPropagation()
        e.preventDefault()
      }}
    >
      {children}
    </span>
  </Tooltip>
}

function MenuItemCom(props: { item: MenuItem; hideMenu: () => void }) {
  const { icon = null, title, disabled = false, disabledTips = '', onClick } = props.item
  const { hideMenu } = props

  const wrappedOnClick = useCallback(
    (e: React.MouseEvent<HTMLAnchorElement>) => {
      e.stopPropagation()
      if (disabled) return
      hideMenu()
      onClick(e)
    },
    [disabled, onClick, hideMenu],
  )

  const className = c(disabled && 'qun-beauty-menu-disabled')

  const content = <a onClick={wrappedOnClick} className={className}>
    {icon}
    <span>{title}</span>
  </a>
  return disabled && truthy(disabledTips) ? (
    <Tooltip title={disabledTips} overlayClassName="qun-beauty-menu-disabled-tips">
      {content}
    </Tooltip>
  ) : (
    content
  )
}
